package com.boyon.system.provider;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.boyon.common.exection.BusinessException;
import com.boyon.common.exection.SystemException;
import com.boyon.common.status.CodingType;
import com.boyon.common.status.PreffixType;
import com.boyon.common.tools.DateFormatStyle;
import com.boyon.common.tools.DateTool;
import com.boyon.common.tools.ObjectTool;
import com.boyon.common.tools.StringTool;
import com.boyon.redis.adapter.JedisAdapter;
import com.boyon.redis.wrap.JedisWrap;
import com.boyon.service.CodingProviderService;
import com.boyon.system.entity.Coding;
import com.boyon.system.service.CodingService;

/**
 * ClassName:CodingProviderServiceImpl <br/>
 * Function: 编码生成服务类实现. <br/>
 * Date: 2018年4月2日 下午2:00:44 <br/>
 * 
 * @author sunshulin
 * @version
 * @since JDK 1.8
 * @see
 */
@Service("codingProviderService")
public class CodingProviderServiceImpl implements CodingProviderService {

	@Autowired
	private CodingService codingService;
	@Autowired
	private JedisAdapter jedisAdapter;

	private static final int database = 5;
	
	public String createCoding(String codingKey) {
		return createCoding(codingKey, null);
	}

	public String createCoding(String codingKey, String preffix) {
		if (!StringTool.isNotNull(codingKey)) {
			throw BusinessException.builder(0, "codingKey没有填写");
		}
		Coding coding = codingService.findByCodingKey(codingKey);
		if (!ObjectTool.isNotNull(coding)) {
			throw BusinessException.builder(0, "编码不存在");
		}
		if (CodingType.c1.getVal() == coding.getCodingType()) {
			// 固定编码生成规则
			return preffix(coding);
		} else if (CodingType.c2.getVal() == coding.getCodingType()) {
			// 层次编码生成规则
			return level(coding, preffix);
		} else {
			throw SystemException.builder(0, "编码类型未知");
		}
	}

	/**
	 * 
	 * preffix:固定. <br/>
	 * 
	 * @author sunshulin
	 * @param coding
	 * @return
	 * @since JDK 1.8
	 */
	private String preffix(Coding coding) {
		String key = coding.getCodingKey();
		String preffix = StringTool.space;
		if (PreffixType.date.getVal() == coding.getPreffixType()) {
			String date = DateTool.format(new Date(), DateFormatStyle.year);
			key += date;
			preffix = date;
		} else if (PreffixType.chara.getVal() == coding.getPreffixType()) {
			key += coding.getPreffix();
			preffix = coding.getPreffix();
		}
		Long inc = getInc(key);
		String style = coding.getStyle();
		return String.format("%s%0" + style + "d", preffix, inc);
	}

	/**
	 * 
	 * level:. 层级编码生成规则<br/>
	 * 
	 * @author sunshulin
	 * @param coding
	 * @return
	 * @since JDK 1.8
	 */
	private String level(Coding coding, String preffix) {
		String[] styles = coding.getStyle().split(",");
		int lvl = 0;
		if (StringTool.isNotNull(preffix)) {
			int length = preffix.length();
			for (int i = 0; i < styles.length; i++) {
				int index = i + 1;
				if (length == Integer.parseInt(styles[i])
						&& index < styles.length) {
					lvl = index;
				} else if (index >= styles.length) {
					throw SystemException.builder(0, "超出层级编码范围");
				}
			}
		}
		String key = coding.getCodingKey();
		if (StringTool.isNotNull(preffix)) {
			key += preffix;
		}
		Long inc = getInc(key);
		return String.format("%s%0" + styles[lvl] + "d", preffix, inc);
	}

	/**
	 * 
	 * getInc:获取部长. <br/>
	 * 
	 * @author sunshulin
	 * @param key
	 * @return
	 * @since JDK 1.8
	 */
	private Long getInc(String key) {
		Long inc = 1L;
		JedisWrap jedisWrap = jedisAdapter.getResource();
		try {
			jedisWrap.selectDatabase(database);
			inc = jedisWrap.hincrBy("serial", key, 1L);
		} finally {
			jedisWrap.release();
		}
		return inc;
	}
}